package net.toby200.canalbuddy.notices.notification;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;

import net.toby200.canalbuddy.R;
import net.toby200.canalbuddy.notices.MainActivity;
import net.toby200.canalbuddy.notices.model.Notice;

import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;

/**
 * Manages list of pending Notice notifications. When new notifications come in these are added to the list
 * so the updated notification shows a summary of all the pending notices; when notifications are cleared it then
 * removes them so further notifications are then shown from scratch.
 *
 * The main aim is to keep the notification to a reasonable size by adjusting display as follows:
 * 1 notification - show title and description
 * 2-4 notifications at once - show all 3 titles
 * 5+ notifications - just show total count
 *
 * Created by toby on 28/11/2014.
 */
public class NoticeNotificationManager extends Service {
    private static final Logger LOG = Logger.getLogger(NoticeNotificationManager.class.getName());

    /**
     * The unique identifier for this type of notification.
     */
    private static final String NOTIFICATION_TAG = "NOTICE";

    // set of all notice notifications that haven't been cleared yet
    private Set<Notice> pendingNotices = new HashSet<Notice>();

    @Override
    public ComponentName startService(Intent service) {
        LOG.info("starting NoticeNotificationManager IntentService");
        return super.startService(service);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent == null) {
            return Service.START_STICKY;
        }

        if (intent.hasExtra("net.toby200.canalbuddy.NOTICE")) {
            // main activity has been called from something e.g. notification with attached notice so
            // startup with this notice showing
            Notice notice = intent.getParcelableExtra("net.toby200.canalbuddy.NOTICE");
            LOG.info("Received notice in intent: " + notice);
            addNoticeNotification(getApplicationContext(), notice);
        } else if (intent.hasExtra("net.toby200.canalbuddy.NOTICE_CLEAR")) {
            pendingNotices.clear();
            LOG.info("Cleared pending notice notifications");
        }

        return Service.START_STICKY; // keep the service running
    }

    @Override
    public IBinder onBind(Intent intent) {
        // for communication return IBinder implementation
        return null;
    }

    // add a new notice to the set of pending notice notifications
    public void addNoticeNotification(Context context, Notice notice) {
        pendingNotices.add(notice);
        createOrUpdateNotification(context);
    }

    /**
     * Shows the notification, or updates a previously shown notification of
     * this type, with the given context.
     */
    public void createOrUpdateNotification(final Context context) {
        Intent onclickIntent = new Intent(context, MainActivity.class);
        if (pendingNotices.size() == 1) {
            onclickIntent.putExtra("net.toby200.canalbuddy.NOTICE",  pendingNotices.iterator().next());
            LOG.info("OnClickIntent set to load specific notice");
        } else {
            LOG.info("OnClickIntent set to load notice list screen");
            onclickIntent.putExtra("net.toby200.canalbuddy.NOTICE_LIST", true);
        }
        onclickIntent.putExtra("net.toby200.canalbuddy.NOTICE_CLEAR", true);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, -1, onclickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        PendingIntent deleteIntent = PendingIntent.getBroadcast(
                context, 0, new Intent(context, NotificationClearedReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);

        final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                .setDefaults(Notification.DEFAULT_ALL)
                .setSmallIcon(R.drawable.ic_stat_)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setNumber(pendingNotices.size())
                .setContentIntent(pendingIntent)
                .setDeleteIntent(deleteIntent)
                .setAutoCancel(true) // delete when clicked
                .setOnlyAlertOnce(false);

        Resources res = context.getResources();

        if (pendingNotices.size() == 1) {
            Notice notice = pendingNotices.iterator().next();
            buildSingleNotification(builder, res, notice);
        } else if (pendingNotices.size() < 5) {
            buildFewNotifications(builder, res, pendingNotices);
        } else {
            buildManyNotification(builder, res, pendingNotices);
        }

        notify(context, builder.build());
    }

    private NotificationCompat.Builder buildManyNotification(NotificationCompat.Builder builder, Resources res, Set<Notice> notices) {
        final String text = notices.size() + " new canal notices have been added.";

        return builder
                .setContentTitle(res.getString(R.string.notification_title))
                .setContentText(text);
    }

    private NotificationCompat.Builder buildFewNotifications(NotificationCompat.Builder builder, Resources res, Set<Notice> notices) {
        final String title = "Multiple CanalBuddy Notices (" + notices.size() + ")";
        final StringBuilder text = new StringBuilder();
        NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();

        for (Notice notice : notices) {
            text.append(notice.getTitle());
            style.addLine(notice.getTitle());
        }

        return builder
                .setContentTitle(res.getString(R.string.notification_title))
                .setContentText(text)

                // Show expanded text content on devices running Android 4.1 or later
                .setStyle(style
                    .setBigContentTitle(title)
                    .setSummaryText("New notices:")
                )
                ;
    }

    private NotificationCompat.Builder buildSingleNotification(NotificationCompat.Builder builder, Resources res, Notice notice) {
        final String title = notice.getTitle();
        final String text = notice.getDescription();

        return builder
                .setContentTitle(res.getString(R.string.notification_title))
                .setContentText(text)

                // Show expanded text content on devices running Android 4.1 or later
                .setStyle(new NotificationCompat.BigTextStyle()
                                .bigText(text)
                                .setBigContentTitle(title)
                                .setSummaryText(notice.getDescription())
                )
                ;
    }

    @TargetApi(Build.VERSION_CODES.ECLAIR)
    private static void notify(final Context context, final Notification notification) {
        final NotificationManager nm = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
            nm.notify(NOTIFICATION_TAG, 0, notification);
        } else {
            nm.notify(NOTIFICATION_TAG.hashCode(), notification);
        }
    }

}
